package com.gqqx.user.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gqqx.common.exception.CustomException;
import com.gqqx.common.utils.Spearman;
import com.gqqx.user.mapper.WeatherMapper;
import com.gqqx.user.pojo.Weather;
import com.gqqx.user.pojo.vo.WeatherHourVo;
import com.gqqx.user.pojo.vo.WeatherVo;
import com.gqqx.user.service.WeatherService;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class WeatherServiceImpl extends ServiceImpl<WeatherMapper, Weather> implements WeatherService {


    @Autowired
    private WeatherMapper weatherMapper;

    /**
     * 返回气象编号和名称
     * @return
     */
    @Override
    public List<Map<Integer, String>> findStations() {
        return weatherMapper.findStations();
    }

    /**
     * 查询气象日期信息
     * @param station
     * @return
     */
    @Override
    public List<String> findStationsDate(String station) {
        return weatherMapper.findStationsDate(station);
    }

    //指定复杂查询条件的气象数据
    @Override
    public List<List<String>> findWeatherWhole(WeatherVo weatherVo) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (StringUtils.isEmpty(weatherVo.getStation())){
            throw new CustomException("气象站编号为空");
        }
        if (StringUtils.isEmpty(weatherVo.getStart_date())){
            throw new CustomException("开始日期为空");
        }
        if (StringUtils.isEmpty(weatherVo.getEnd_date())){
            Date date = new Date();
            weatherVo.setEnd_date(simpleDateFormat.format(date));
        }
        List<Weather> weatherWhole = weatherMapper.findWeatherWhole(weatherVo);
        List<List<String>> list2 = new ArrayList<>();
        for (Weather weather : weatherWhole) {
            List<String> list1 = new ArrayList<>();
            list1.add(simpleDateFormat.format(weather.getDate()));
            list1.add(weather.getTemperature());
            list1.add(weather.getHumidity());
            list1.add(weather.getSpeed());
            list1.add(weather.getDirection());
            list1.add(weather.getRain());
            list1.add(weather.getSunlight());
            list1.add(weather.getPm25());
            list1.add(weather.getPm10());
            list2.add(list1);
        }
        return list2;
    }

    //获取任意时间段以天为单位的气象数据
    @Override
    public List<String> findStatDayRange(String station, String start_date, String end_date, String which) {
        if (StringUtils.isEmpty(station)){
            throw  new CustomException("气象站编号为空");
        }
        if (StringUtils.isEmpty(start_date)){
            throw  new CustomException("开始时间参数为空");
        }
        if (StringUtils.isEmpty(end_date)){
            throw  new CustomException("结束时间参数为空");
        }
        if (StringUtils.isEmpty(which)){
            throw  new CustomException("气象因素为空");
        }
        int num = calcBetweenDate(start_date, end_date);
        String[] countArr = new String[num];
        Date date1 = new Date();
        try {
            date1 = new SimpleDateFormat("yyyy-MM-dd").parse(start_date);
        } catch (ParseException e) {
            throw new CustomException("时间转换格式错误");
        }
        LocalDate localDate = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        String Date = String.valueOf(localDate);
        List<WeatherHourVo> weatherHourVoList = weatherMapper.findStatDayRange(station,countArr, String.valueOf(Date));
        List<String> list = new ArrayList<>();
        for (WeatherHourVo weatherHourVo : weatherHourVoList) {
            Weather weather = new Weather();
            BeanUtils.copyProperties(weatherHourVo,weather);
            String transformation = transformation(which, weather);
            if (StringUtils.isEmpty(transformation)) transformation = "0";
            list.add(transformation);
        }
        return list;
    }
    //计算任一时间段内气象数据的协相关矩阵
    @Override
    public List<String> findCorrelation(String station, String start_date, String end_date, String[] correlation) {
        if (StringUtils.isEmpty(station)){
            throw  new CustomException("气象站编号为空");
        }
        if (StringUtils.isEmpty(start_date)){
            throw  new CustomException("开始时间参数为空");
        }
        if (StringUtils.isEmpty(end_date)){
            throw  new CustomException("结束时间参数为空");
        }
        if (correlation == null || correlation.length<2){
            throw  new CustomException("气象因素数组为空或只有一个值");
        }
        List<Weather> weatherList = weatherMapper.findCorrelation(station,start_date,end_date);
        List<Double> temperatures = new ArrayList<>();
        List<Double> humiditys = new ArrayList<>();
        List<Double> speeds = new ArrayList<>();
        List<Double> directions = new ArrayList<>();
        List<Double> rains = new ArrayList<>();
        List<Double> sunlights = new ArrayList<>();
        List<Double> pm25s = new ArrayList<>();
        List<Double> pm10s = new ArrayList<>();
        for (Weather weather : weatherList) {
            temperatures.add(Double.parseDouble(weather.getTemperature()));
            humiditys.add(Double.parseDouble(weather.getHumidity()));
            speeds.add(Double.parseDouble(weather.getSpeed()));
            directions.add(Double.parseDouble(weather.getDirection()));
            rains.add(Double.parseDouble(weather.getRain()));
            sunlights.add(Double.parseDouble(weather.getSunlight()));
            pm25s.add(Double.parseDouble(weather.getPm25()));
            pm10s.add(Double.parseDouble(weather.getPm10()));
        }
        double[] temperatures1 = temperatures.stream().mapToDouble(i->i).toArray();
        double[] humiditys1 = humiditys.stream().mapToDouble(i->i).toArray();
        double[] speeds1 = speeds.stream().mapToDouble(i->i).toArray();
        double[] directions1 = directions.stream().mapToDouble(i->i).toArray();
        double[] rains1 = rains.stream().mapToDouble(i->i).toArray();
        double[] sunlights1 = sunlights.stream().mapToDouble(i->i).toArray();
        double[] pm25s1 = pm25s.stream().mapToDouble(i->i).toArray();
        double[] pm10s1 = pm10s.stream().mapToDouble(i->i).toArray();
        List<String> list1 = new ArrayList<>();
        for (String s1 : correlation){
            double[] transformation1 = transformation(s1, temperatures1, humiditys1, speeds1, directions1, rains1, sunlights1, pm25s1, pm10s1);
            List<String> list2 = new ArrayList<>();
            for (String s2 : correlation) {
                double[] transformation2 = transformation(s2, temperatures1, humiditys1, speeds1, directions1, rains1, sunlights1, pm25s1, pm10s1);
                Spearman sp = new Spearman(transformation1,transformation2);
                list2.add(String.valueOf(sp.getR()));
            }
            list1.add(String.valueOf(list2));
        }
        return list1;
    }

    //获取任一小时的分钟气象信息
    @Override
    public List<String> findHourWeather(String station, String date, String hour, String which) {
        if (StringUtils.isEmpty(station)){
            throw  new CustomException("气象站编号为空");
        }
        if (StringUtils.isEmpty(date)){
            throw  new CustomException("时间参数为空");
        }
        if (StringUtils.isEmpty(hour)){
            throw  new CustomException("小时时间参数为空");
        }
        if (StringUtils.isEmpty(which)){
            throw  new CustomException("气象因素为空");
        }
        //避免前端传过来有分十秒
        Date date1 = new Date();
        try {
            date1 = new SimpleDateFormat("yyyy-MM-dd").parse(date);
        } catch (ParseException e) {
            throw new CustomException("时间转换格式错误");
        }
        LocalDate localDate = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        String Date = String.valueOf(localDate);

        String dateHour = null;
        if (hour.length() == 1) {
            dateHour = Date + " 0" + hour + ":00:00";
        }
        if (hour.length() == 2) {
            dateHour = Date + " " + hour + ":00:00";
        }
        List<Weather> weatherList = weatherMapper.findHourWeather(station,dateHour);

        List<String> list = new ArrayList<>();
        for (Weather weather:weatherList){
            list.add(transformation(which,weather));
        }
        return list;
    }

    //获取任一天的小时气象信息
    @Override
    public List<String> findDayHour(String station, String date, String which) {
        if (StringUtils.isEmpty(station)){
            throw  new CustomException("气象站编号为空");
        }
        if (StringUtils.isEmpty(date)){
            throw  new CustomException("时间参数为空");
        }
        if (StringUtils.isEmpty(which)){
            throw  new CustomException("气象因素为空");
        }
        Date date1 = new Date();
        try {
            date1 = new SimpleDateFormat("yyyy-MM-dd").parse(date);
        } catch (ParseException e) {
            throw new CustomException("时间转换格式错误");
        }
        LocalDate localDate = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        List<WeatherHourVo> weatherHourVoList = weatherMapper.findDayHour(station, String.valueOf(localDate));
        List<String> list = new ArrayList<>();
        for (WeatherHourVo weatherHourVo : weatherHourVoList) {
            Weather weather = new Weather();
            BeanUtils.copyProperties(weatherHourVo,weather);
            list.add(transformation(which,weather));
        }
        return list;
    }

    public int calcBetweenDate(String start, String end) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Date startDate = null;
        Date endDate = null;
        try {
            startDate = df.parse(start);
            endDate = df.parse(end);
        } catch (Exception e) {
            System.out.println("日期转换出错");
        }
        int count = (int) ((endDate.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1000));
        return count;
    }

    private String transformation(String w,Weather weather){
        int i = Integer.parseInt(w);
        switch (i){
            case 1:
                return weather.getTemperature();
            case 2:
                return weather.getHumidity();
            case 3:
                return weather.getSpeed();
            case 4:
                return weather.getDirection();
            case 5:
                return weather.getRain();
            case 6:
                return weather.getSunlight();
            case 7:
                return weather.getPm25();
            case 8:
                return weather.getPm10();
        }
        throw new CustomException("因素不匹配");
    }

    private double[] transformation(String w, double[] temperatures, double[] humiditys,
                                        double[] speeds, double[] directions, double[] rains,
                                        double[] sunlights, double[] pm25s, double[] pm10s){
        int i = Integer.parseInt(w);
        switch (i){
            case 1:
                return temperatures;
            case 2:
                return humiditys;
            case 3:
                return speeds;
            case 4:
                return directions;
            case 5:
                return rains;
            case 6:
                return sunlights;
            case 7:
                return pm25s;
            case 8:
                return pm10s;
        }
        throw new CustomException("因素不匹配");
    }
}


